package com.swiftops.common.configure;

import com.alibaba.fastjson.JSON;
import com.swiftops.common.constant.AuthConstant;
import com.swiftops.common.core.ApiResult;
import com.swiftops.common.model.TokenModel;
import com.swiftops.common.service.ThreadLocalUserService;
import com.swiftops.common.service.TokenService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;

@Slf4j
@Component
public class AuthInterceptor extends HandlerInterceptorAdapter {
    @Autowired
    private TokenService tokenService;
    @Autowired
    private ThreadLocalUserService threadLocalUserService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (validateSign(request, handler)) {
            return true;
        }
        String format = String.format("签名认证失败，请求接口：%s，请求IP：%s，请求参数：%s", request.getRequestURI(), getIpAddress(request), JSON.toJSONString(request.getParameterMap()));
        log.error(format);
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        responseResult(response, new ApiResult(401, "签名认证失败", null));
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        //super.postHandle(request, response, handler, modelAndView);
//        System.out.println("------postHandle------");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //super.afterCompletion(request, response, handler, ex);
//        System.out.println("------afterCompletion------");
    }

    /**
     * 验证签名，如果验证通过，设置当前用户信息。
     *
     * @param request 请求对象
     * @param handler 处理程序对象
     * @return 验证通过返回true，否则返回false
     */
    private boolean validateSign(HttpServletRequest request, Object handler) {
        //如果不是映射到方法直接通过
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();

        String authorization = request.getHeader(AuthConstant.AUTHORIZATION);
        if (StringUtils.isBlank(authorization)) {
            authorization = request.getParameter(AuthConstant.AUTHORIZATION);
        }

        TokenModel model = tokenService.getTokenModel(authorization);
        if (tokenService.checkToken(model)) {
            threadLocalUserService.setUser(model.getUser());
            request.setAttribute(AuthConstant.CURRENT_USER, model.getUser());
            return true;
        } else {
            //检查方法上是否有PermitAll或IgnoreSecurity注解。
            if (method.isAnnotationPresent(javax.annotation.security.PermitAll.class) ||
                    method.isAnnotationPresent(com.swiftops.common.annotation.IgnoreSecurity.class)) {
                return true;
            }
            return false;
        }
    }

    /**
     * 生成返回结果
     *
     * @param response 返回参数
     * @param result   结果
     */
    public static void responseResult(HttpServletResponse response, ApiResult result) {
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-type", "application/json;charset=UTF-8");
        try {
            response.getWriter().write(JSON.toJSONString(result));
        } catch (IOException ex) {
            log.error(ex.getMessage());
        }
    }

    private String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        // 如果是多级代理，那么取第一个ip为客户端ip
        if (ip != null && ip.indexOf(",") != -1) {
            ip = ip.substring(0, ip.indexOf(",")).trim();
        }
        return ip;
    }
}
